//Programma gestione acquario


//#include <string.h>
#include <LCD4Bit_mod.h>
#include <OneWire.h>
#include <Wire.h>
#include "RTClib.h"
#include <Time.h>
#include <TimeAlarms.h>
#include <stdio.h>
#include <EEPROM.h>


byte addr[8];

char msgs[12][17] = {"MENU PRINCIPALE ",
                    "1. FEED MODE    ", 
                    "2. TEMPERATURA  ", 
                    "3. NEON         ",
                    "4. HQI          ",
                    "5. LUNARI       ",
                    "6. POMPA SX     ",
                    "7. POMPA DX     ",
                    "8. RABBOCCO     ",
                    "9. OROLOGIO     ",
                    "10. COOLER      ",
                    "11. DISTANZA    "};
                    
char subMenuNEON[4][17] = {"3.1 MANUAL      ",
                           "3.2 SET TIME ON ",
                           "3.3 SET TIME OFF",
                           "3.4 BACK        "}; 

char subMenuHQI[4][17] = {"4.1 MANUAL      ",
                           "4.2 SET TIME ON ",
                           "4.3 SET TIME OFF",
                           "4.4 BACK        "}; 

char subMenuMoon[4][17] = {"5.1 MANUAL      ",
                           "5.2 SET TIME ON ",
                           "5.3 SET TIME OFF",
                           "5.4 BACK        "}; 

char subMenuCooler[4][17] = {"10.1 MANUAL     ",
                             "10.2 SET MIN T  ",
                             "10.3 SET MAX T  ",
                             "10.4 BACK       "}; 

//Global Variables for the Application

#define DS18S20_ID 0x10
#define DS18B20_ID 0x28


#define LCDrxpin  5//not used
#define LCDtxpin  6//we only transmit

#define KeyPin  1 //which analog pin is used for the 5 key pad

#define KeyLeft  3
#define KeyRight 0
#define KeyUp    1
#define KeyDown  2
#define KeySel   4
#define KeyInv   60   //invalid key value
#define temperature_pin 19
#define distance_pin 15
#define temperature_pwr_pin 52

#define neon_pin  53
#define hqi_pin  51
#define moon_pin  49
#define pumpsx_pin  47
#define pumpdx_pin  45
#define refill_pin  43
#define cooler_pin  41
#define pwr_relais_pin 37

#define NeonOnHourMem    50
#define NeonOnMinuteMem  52
#define NeonOffHourMem   54
#define NeonOffMinuteMem 56

#define HQIOnHourMem    58
#define HQIOnMinuteMem  60
#define HQIOffHourMem   62
#define HQIOffMinuteMem 64

#define MoonOnHourMem    66
#define MoonOnMinuteMem  68
#define MoonOffHourMem   70
#define MoonOffMinuteMem 72

#define CoolerMinMem     74
#define CoolerMaxMem     76



int  adc_key_val[5] ={30, 150, 360, 535, 760 };

//variabili flag vari
int neon_fl;
int hqi_fl;
int moon_fl;
int pumpsx_fl;
int pumpdx_fl;
int refill_fl;
int force_refill_fl;
int cooler_fl;

//allarmi
AlarmId NeonOnAlarm;
AlarmId NeonOffAlarm;
AlarmId HQIOnAlarm;
AlarmId HQIOffAlarm;
AlarmId MoonOnAlarm;
AlarmId MoonOffAlarm;


// variabili per settaggi di sistema
int NeonOnHour;
int NeonOnMinute;
int NeonOffHour;
int NeonOffMinute;
int HQIOnHour;
int HQIOnMinute;
int HQIOffHour;
int HQIOffMinute;
int MoonOnHour;
int MoonOnMinute;
int MoonOffHour;
int MoonOffMinute;
int first_distance_fl;
float min_distance;
int hi_temp;
int lo_temp;
int fl_feed;

//create object to control an LCD.  
LCD4Bit_mod lcd = LCD4Bit_mod(2); 

RTC_DS1307 RTC;
OneWire ds(temperature_pin);

int NUM_KEYS = 5;
int adc_key_in;
int key=-1;
int oldkey=-1;
int offset = 0;
float OneWireTemp;

void setup() { 
  Serial.begin(9600);
  Wire.begin();
  RTC.begin();
  //RTC.adjust(DateTime(__DATE__, __TIME__)); //setta l'ora del PC

  pinMode(13, OUTPUT);  //we'll use the debug LED to output a heartbeat
  pinMode(temperature_pwr_pin, OUTPUT);
  
  pinMode(neon_pin, OUTPUT);
  pinMode(hqi_pin, OUTPUT);
  pinMode(moon_pin, OUTPUT);
  pinMode(pumpsx_pin, OUTPUT);
  pinMode(pumpdx_pin, OUTPUT);
  pinMode(refill_pin, OUTPUT);
  pinMode(cooler_pin, OUTPUT);
  pinMode(pwr_relais_pin, OUTPUT);
  
  digitalWrite(pwr_relais_pin, HIGH);
  
  DateTime now = RTC.now();
  
  setTime(now.hour(),now.minute(), now.second(), now.day(), now.month(), now.year()); // set time to 20:30:00 Jan 1 2012

  neon_fl = EEPROM.read(neon_pin * 2);
  hqi_fl = EEPROM.read(hqi_pin * 2);
  moon_fl = EEPROM.read(moon_pin * 2);
  pumpsx_fl = EEPROM.read(pumpsx_pin * 2);
  pumpdx_fl =  EEPROM.read(pumpdx_pin * 2);
  refill_fl =  0;
  cooler_fl = 0;
  first_distance_fl = 0;
  min_distance = 29.0;
  
  fl_feed = 0;
  
  //NEON Attinico get orari da memoria
  NeonOnHour = EEPROM.read(NeonOnHourMem);
  if (NeonOnHour == -1 || NeonOnHour > 60){
    NeonOnHour = 14;
    EEPROM.write(NeonOnHourMem, NeonOnHour);
  }
  NeonOnMinute = EEPROM.read(NeonOnMinuteMem);
  if (NeonOnMinute == -1 || NeonOnMinute > 60){
    NeonOnMinute = 25;
    EEPROM.write(NeonOnMinuteMem, NeonOnMinute);
  }
  NeonOffHour = EEPROM.read(NeonOffHourMem);
  if (NeonOffHour == -1 || NeonOffHour > 24){
    NeonOffHour = 22;
    EEPROM.write(NeonOffHourMem, NeonOffHour);
  }
  NeonOffMinute = EEPROM.read(NeonOffMinuteMem);
  if (NeonOffMinute == -1 || NeonOffMinute > 60){
    NeonOffMinute = 35;
    EEPROM.write(NeonOffMinuteMem, NeonOffMinute);
  }

  //HQI get orari da memoria
  HQIOnHour = EEPROM.read(HQIOnHourMem);
  if (HQIOnHour == -1 || HQIOnHour > 24){
    HQIOnHour = 14;
    EEPROM.write(HQIOnHourMem, HQIOnHour);
  }
  HQIOnMinute = EEPROM.read(HQIOnMinuteMem);
  if (HQIOnMinute == -1 || HQIOnMinute > 60){
    HQIOnMinute = 30;
    EEPROM.write(HQIOnMinuteMem, HQIOnMinute);
  }
  HQIOffHour = EEPROM.read(HQIOffHourMem);
  if (HQIOffHour == -1 || HQIOffHour > 24){
    HQIOffHour = 22;
    EEPROM.write(HQIOffHourMem, HQIOffHour);
  }
  HQIOffMinute = EEPROM.read(HQIOffMinuteMem);
  if (HQIOffMinute == -1 || HQIOffMinute > 60){
    HQIOffMinute = 30;
    EEPROM.write(HQIOffMinuteMem, HQIOffMinute);
  }

  //Lunari get orari da memoria
  MoonOnHour = EEPROM.read(MoonOnHourMem);
  if (MoonOnHour == -1 || MoonOnHour > 24){
    MoonOnHour = 22;
    EEPROM.write(MoonOnHourMem, MoonOnHour);
  }
  MoonOnMinute = EEPROM.read(MoonOnMinuteMem);
  if (MoonOnMinute == -1 || MoonOnMinute > 60){
    MoonOnMinute = 34;
    EEPROM.write(MoonOnMinuteMem, MoonOnMinute);
  }
  MoonOffHour = EEPROM.read(MoonOffHourMem);
  if (MoonOffHour == -1 || MoonOffHour > 24){
    MoonOffHour = 8;
    EEPROM.write(MoonOffHourMem, MoonOffHour);
  }
  MoonOffMinute = EEPROM.read(MoonOffMinuteMem);
  if (MoonOffMinute == -1 || MoonOffMinute > 60){
    MoonOffMinute = 30;
    EEPROM.write(MoonOffMinuteMem, MoonOffMinute);
  }

  hi_temp = EEPROM.read(CoolerMaxMem);
  if (hi_temp == -1 || hi_temp > 30){
    hi_temp = 27;
    EEPROM.write(CoolerMaxMem, hi_temp);
  }
  lo_temp = EEPROM.read(CoolerMinMem);
  if (lo_temp == -1 || lo_temp > 30){
    lo_temp = 27;
    EEPROM.write(CoolerMinMem, lo_temp);
  }
  
  // neon attinico
  NeonOnAlarm = Alarm.alarmRepeat(NeonOnHour,NeonOnMinute,0, NeonOn);  // 14:30am every day
  NeonOffAlarm = Alarm.alarmRepeat(NeonOffHour,NeonOffMinute,0, NeonOff);  // 23:30am every day
  // HQI
  HQIOnAlarm = Alarm.alarmRepeat(HQIOnHour,HQIOnMinute,0, HQIOn);  // 14:30am every day
  HQIOffAlarm = Alarm.alarmRepeat(HQIOffHour,HQIOffMinute,0, HQIOff);  // 23:30am every day
  // Lunari
  MoonOnAlarm = Alarm.alarmRepeat(MoonOnHour,MoonOnMinute,0, MoonOn);  // 22:30am every day
  MoonOffAlarm = Alarm.alarmRepeat(MoonOffHour,MoonOffMinute, 0, MoonOff);  // 08:30am every day
  //pompa movimento sx
  Alarm.alarmRepeat(0,0,0, PumpSwitchSx);  // 00:00am every day
  Alarm.alarmRepeat(6,0,0, PumpSwitchDx);  // 00:00am every day
  Alarm.alarmRepeat(12,0,0, PumpSwitchSx);  // 00:00am every day
  Alarm.alarmRepeat(18,0,0, PumpSwitchDx);  // 00:00am every day
  
  Alarm.timerRepeat(10,SetStatus);
  
  lcd.init();
  lcd.clear();
   
}

void loop() {
        
        char strKey[15];
        int sample;
        int i; 
        float voltage; float temp;

        //digitalClockDisplay();
        lcd.cursorTo(1, 0);  //line=2, x=0
        lcd.printIn(msgs[offset]);
	adc_key_in = analogRead(0);    // read the value from the sensor  
        digitalWrite(13, HIGH);  
        Alarm.delay(50);
        key = get_key(adc_key_in);		        // convert into key press
	if (key != oldkey)				    // if keypress is detected
	{
                Alarm.delay(50);		        // wait for debounce time
		adc_key_in = analogRead(0);     // read the value from the sensor  
                key = get_key(adc_key_in);	// convert into key press
                if (key != oldkey)				
                {

                      switch(key) {
	                 case 1: //UP
	                    if (offset > 0) offset--;
	                    break;
	                 case 2: //DOWN
	                    if (offset < 12) offset++;
	                    break;
	                 case 4: //SELECT
	                    switch (offset) {
                  		 case 1://Modo Manuale
                  		    FeedMode();
                  		    break;
                  		 case 2: //temperatura
                                    TempManual();
                   		    break;
                                case 3: //Neon
                  		    MenuNeon(); 
                  		    break;
                                case 4: //HQI
                  		    MenuHQI();
                  		    break;
                                case 5: //Moon
                  		    MenuMoon();
                  		    break;
                                case 6: //Pompa Sx
                  		    PumpSxManual();
                  		    break;
                                case 7: //Pompa Dx
                  		    PumpDxManual();
                  		    break;
                                case 8: //Pompa Rabbocco
                  		    RefillManual();
                  		    break;
                                case 9://Orologio
                  		    Orologio();
                  		    break;
                                case 10: //Raffreddatore
                  		    MenuCooler();
                  		    break;
                                case 11: //Raffreddatore
                  		    TestDistanza();
                  		    break;
	                    }
	                    break;			
                    }
                    oldkey = key;
                    if (offset >=0){
                        lcd.cursorTo(1, 0);  //line=2, x=0
                        lcd.printIn(msgs[offset]);
                    
                }
            }
  }
  
  digitalWrite(13, LOW);
  
}

void MenuNeon()
{
int offset = 0;
  
  lcd.cursorTo(1, 0);  //line=2, x=0
  lcd.printIn(subMenuNEON[offset]);

  for(;;)
  {
  Alarm.delay(50);
  adc_key_in = analogRead(0);     // read the value from the sensor  
        
        key = get_key(adc_key_in);		        // convert into key press
	if (key != oldkey)				    // if keypress is detected
	{
                Alarm.delay(50);		        // wait for debounce time
		adc_key_in = analogRead(0);     // read the value from the sensor  
                key = get_key(adc_key_in);	// convert into key press
                if (key != oldkey)				
                {

                      switch(key) {
	                 case 1: //UP
                            Serial.println("up");
	                    if (offset > 0) offset--;
	                    break;
	                 case 2: //DOWN
                            Serial.println("down");
	                    if (offset < 3) offset++;
	                    break;
	                 case 4: //SELECT
                            Serial.println("select");
	                    switch (offset) {
                  		 case 0://Modo Manuale
                  		    NeonManual();
                  		    break;
                  		 case 1: //Setta accensione
                                    CambiaOrario(subMenuNEON[offset], NeonOnHour, NeonOnMinute);
                                    //salvo i valori su EEPROM
                                    EEPROM.write(NeonOnHourMem, NeonOnHour);
                                    EEPROM.write(NeonOnMinuteMem, NeonOnMinute);
                                    //resetto allarme
                                    Alarm.free(NeonOnAlarm);
                                    NeonOnAlarm = Alarm.alarmRepeat(NeonOnHour,NeonOnMinute,0, NeonOn);
                  		    break;
                  		 case 2: //Setta spegnimento
                                    CambiaOrario(subMenuNEON[offset], NeonOffHour, NeonOffMinute);
                                    //salvo i valori su EEPROM
                                    EEPROM.write(NeonOffHourMem, NeonOffHour);
                                    EEPROM.write(NeonOffMinuteMem, NeonOffMinute);
                                    //resetto allarme
                                    Alarm.free(NeonOffAlarm);
                                    NeonOffAlarm = Alarm.alarmRepeat(NeonOffHour,NeonOffMinute,0, NeonOff);
                  		    break;
                                 case 3: //back
                                    return;
                                    break;
	                    }
	                    break;			
                    }
                    oldkey = key;
                    if (offset >=0){
                        lcd.cursorTo(1, 0);  //line=2, x=0
                        lcd.printIn(subMenuNEON[offset]);
                    }
            }
      }
  }
}

void MenuHQI()
{
int offset = 0;
  
  lcd.cursorTo(1, 0);  //line=2, x=0
  lcd.printIn(subMenuHQI[offset]);

  for(;;)
  {
  Alarm.delay(50);
  adc_key_in = analogRead(0);     // read the value from the sensor  
        
        key = get_key(adc_key_in);		        // convert into key press
	if (key != oldkey)				    // if keypress is detected
	{
                Alarm.delay(50);		        // wait for debounce time
		adc_key_in = analogRead(0);     // read the value from the sensor  
                key = get_key(adc_key_in);	// convert into key press
                if (key != oldkey)				
                {

                      switch(key) {
	                 case 1: //UP
 	                    if (offset > 0) offset--;
	                    break;
	                 case 2: //DOWN
	                    if (offset < 3) offset++;
	                    break;
	                 case 4: //SELECT
	                    switch (offset) {
                  		 case 0://Modo Manuale
                  		    HQIManual();
                  		    break;
                  		 case 1: //Setta accensione
                                    CambiaOrario(subMenuHQI[offset], HQIOnHour, HQIOnMinute);
                                    //salvo i valori su EEPROM
                                    EEPROM.write(HQIOnHourMem, HQIOnHour);
                                    EEPROM.write(HQIOnMinuteMem, HQIOnMinute);
                                    //resetto allarme
                                    Alarm.free(HQIOnAlarm);
                                    HQIOnAlarm = Alarm.alarmRepeat(HQIOnHour,HQIOnMinute,0, HQIOn);
                  		    break;
                  		 case 2: //Setta spegnimento
                                    CambiaOrario(subMenuHQI[offset], HQIOffHour, HQIOffMinute);
                                    //salvo i valori su EEPROM
                                    EEPROM.write(HQIOffHourMem, HQIOffHour);
                                    EEPROM.write(HQIOffMinuteMem, HQIOffMinute);
                                    //resetto allarme
                                    Alarm.free(HQIOffAlarm);
                                    HQIOffAlarm = Alarm.alarmRepeat(HQIOffHour,HQIOffMinute,0, HQIOff);
                  		    break;
                                 case 3: //back
                                    return;
                                    break;
	                    }
	                    break;			
                    }
                    oldkey = key;
                    if (offset >=0){
                        lcd.cursorTo(1, 0);  //line=2, x=0
                        lcd.printIn(subMenuHQI[offset]);
                    
                }
            }
      }
  }
}

void MenuMoon()
{
int offset = 0;
  
  lcd.cursorTo(1, 0);  //line=2, x=0
  lcd.printIn(subMenuMoon[offset]);

  for(;;)
  {
  Alarm.delay(50);
  adc_key_in = analogRead(0);     // read the value from the sensor  
        
        key = get_key(adc_key_in);		        // convert into key press
	if (key != oldkey)				    // if keypress is detected
	{
                Alarm.delay(50);		        // wait for debounce time
		adc_key_in = analogRead(0);     // read the value from the sensor  
                key = get_key(adc_key_in);	// convert into key press
                if (key != oldkey)				
                {

                      switch(key) {
	                 case 1: //UP
	                    if (offset > 0) offset--;
	                    break;
	                 case 2: //DOWN
	                    if (offset < 3) offset++;
	                    break;
	                 case 4: //SELECT
	                    switch (offset) {
                  		 case 0://Modo Manuale
                  		    MoonManual();
                  		    break;
                  		 case 1: //Setta accensione
                                    CambiaOrario(subMenuMoon[offset], MoonOnHour, MoonOnMinute);
                                    //salvo i valori su EEPROM
                                    EEPROM.write(MoonOnHourMem, MoonOnHour);
                                    EEPROM.write(MoonOnMinuteMem, MoonOnMinute);
                                    //resetto allarme
                                    Alarm.free(MoonOnAlarm);
                                    MoonOnAlarm = Alarm.alarmRepeat(MoonOnHour,MoonOnMinute,0, MoonOn);
                  		    break;
                  		 case 2: //Setta spegnimento
                                    CambiaOrario(subMenuMoon[offset], MoonOffHour, MoonOffMinute);
                                    //salvo i valori su EEPROM
                                    EEPROM.write(MoonOffHourMem, MoonOffHour);
                                    EEPROM.write(MoonOffMinuteMem, MoonOffMinute);
                                    //resetto allarme
                                    Alarm.free(MoonOffAlarm);
                                    MoonOffAlarm = Alarm.alarmRepeat(MoonOffHour,MoonOffMinute,0, MoonOff);
                  		    break;
                                 case 3: //back
                                    return;
                                    break;
	                    }
	                    break;			
                    }
                    oldkey = key;
                    if (offset >=0){
                        lcd.cursorTo(1, 0);  //line=2, x=0
                        lcd.printIn(subMenuMoon[offset]);
                    
                }
            }
      }
  }
}

void MenuCooler()
{
int offset = 0;
  
  lcd.cursorTo(1, 0);  //line=2, x=0
  lcd.printIn(subMenuCooler[offset]);

  for(;;)
  {
  Alarm.delay(50);
  adc_key_in = analogRead(0);     // read the value from the sensor  
        
        key = get_key(adc_key_in);		        // convert into key press
	if (key != oldkey)				    // if keypress is detected
	{
                Alarm.delay(50);		        // wait for debounce time
		adc_key_in = analogRead(0);     // read the value from the sensor  
                key = get_key(adc_key_in);	// convert into key press
                if (key != oldkey)				
                {

                      switch(key) {
	                 case 1: //UP
	                    if (offset > 0) offset--;
	                    break;
	                 case 2: //DOWN
	                    if (offset < 3) offset++;
	                    break;
	                 case 4: //SELECT
	                    switch (offset) {
                  		 case 0://Modo Manuale
                  		    CoolerManual();
                  		    break;
                  		 case 1: //Setta min
                                    CambiaValore(subMenuCooler[offset], lo_temp);
                                    //salvo i valori su EEPROM
                                    EEPROM.write(CoolerMinMem, lo_temp);
                  		    break;
                  		 case 2: //Setta max
                                    CambiaValore(subMenuCooler[offset], hi_temp);
                                    //salvo i valori su EEPROM
                                    EEPROM.write(CoolerMaxMem, hi_temp);
                  		    break;
                                 case 3: //back
                                    return;
                                    break;
	                    }
	                    break;			
                    }
                    oldkey = key;
                    if (offset >=0){
                        lcd.cursorTo(1, 0);  //line=2, x=0
                        lcd.printIn(subMenuCooler[offset]);
                    
                }
            }
      }
  }
}

void CambiaOrario(char* azione, int &ora, int &minuti)
{
  char c_tutto[9];
  int offset = 0;
  Serial.println("Dentro CambiaOrario");
  int n = sprintf(c_tutto, "%02d%c%02d", ora,':',minuti);
  c_tutto[8] = 0;
  lcd.clear();
  lcd.cursorTo(1,0);
  lcd.printIn(azione);
  lcd.cursorTo(2,6);
  lcd.printIn(c_tutto);
  Serial.println(c_tutto);
  for(;;)
  {
  Alarm.delay(50);
  adc_key_in = analogRead(0);     // read the value from the sensor  
        
  key = get_key(adc_key_in);		        // convert into key press
	if (key != oldkey)				    // if keypress is detected
	{
          Alarm.delay(50);		        // wait for debounce time
	  adc_key_in = analogRead(0);     // read the value from the sensor  
          key = get_key(adc_key_in);	// convert into key press
          if (key != oldkey)				
          {

                switch(key) {
                         case 0: //LEFT???
                           Serial.println("premuto left orario");
                           if (offset == 0)
                               offset = 1;
                           else
                               offset = 0;
                            break;   
	                 case 1: //UP
                            Serial.println("premuto up orario");
	                    if (offset == 0){
                              if (ora < 24)
                                ora++;
                            }
                            else {
                              if ( minuti < 60)
                                  minuti++;
	                    }
                            break;
	                 case 2: //DOWN
                            Serial.println("premuto down orario");
	                    if (offset == 0){
                              if (ora > 0)
                                ora--;
                            }
                            else {
                              if (minuti > 0)
                                  minuti--;
	                    }
                            break;
                         case 3: //RIGHT???
                           Serial.println("premuto right orario");
                           if (offset == 0)
                               offset = 1;
                           else
                               offset = 0;
                           break;   
	                 case 4: //SELECT
                              lcd.clear();
                              return;
                              break;
	                 }
                  oldkey = key;
                  n = sprintf(c_tutto, "%02d%c%02d", ora,':',minuti);
                  c_tutto[8] = 0;
                  lcd.cursorTo(2,6);
                  lcd.printIn(c_tutto);
                  Serial.println(c_tutto);
             }
          
      }
    }
  
}

void CambiaValore(char* azione, int &val)
{
  char c_num[5];
  Serial.println("Dentro CambiaValore");
  int n = sprintf(c_num, "%02d", val);
  c_num[3] = 0;
  lcd.clear();
  lcd.cursorTo(1,0);
  lcd.printIn(azione);
  lcd.cursorTo(2,6);
  lcd.printIn(c_num);
  Serial.println(c_num);
  for(;;)
  {
  Alarm.delay(50);
  adc_key_in = analogRead(0);     // read the value from the sensor  
        
  key = get_key(adc_key_in);		        // convert into key press
	if (key != oldkey)				    // if keypress is detected
	{
          Alarm.delay(50);		        // wait for debounce time
	  adc_key_in = analogRead(0);     // read the value from the sensor  
          key = get_key(adc_key_in);	// convert into key press
          if (key != oldkey)				
          {

                switch(key) {
	                 case 1: //UP
                            Serial.println("premuto up");
                            if (val < 45)
                                val++;
                            break;
	                 case 2: //DOWN
                            Serial.println("premuto down");
                            if (val > 15)
                                val--;
                            break;
	                 case 4: //SELECT
                              lcd.clear();
                              return;
                              break;
	                    }
              }
              oldkey = key;
              int n = sprintf(c_num, "%02d", val);
              c_num[3] = 0;
              lcd.cursorTo(2,6);
              lcd.printIn(c_num);
              Serial.println(c_num);
          
      }
    }
  
}

// Convert ADC value to key number
int get_key(unsigned int input)
{
    int k;
    
    for (k = 0; k < NUM_KEYS; k++)
    {
	if (input < adc_key_val[k])
	{
            return k;
        }
    }
    
    if (k >= NUM_KEYS)
        k = -1;     // No valid key pressed
    
    return k;
}

// functions to be called when an alarm triggers:
void NeonOn(){
  //digitalWrite(neon_pin, HIGH);
  neon_fl = 1;
  EEPROM.write(neon_pin * 2, neon_fl);
  Serial.println("Neon On");
}

void NeonOff(){
  //digitalWrite(neon_pin, LOW);
  neon_fl = 0;
  EEPROM.write(neon_pin * 2, neon_fl);
  Serial.println("Neon On");
}

void FeedMode(){

  lcd.cursorTo(0,0);
  lcd.printIn("FEED MODE ON    ");
  //PumpSxOff();
  //PumpDxOff();
  fl_feed = 1;
  Alarm.delay(500);
  for(;;)
  {
    Alarm.delay(50);
    adc_key_in = analogRead(0);    // read the value from the sensor
    key = get_key(adc_key_in);		        // convert into key press
	if (key != oldkey)				    // if keypress is detected
	{
                Alarm.delay(50);		        // wait for debounce time
		adc_key_in = analogRead(0);     // read the value from the sensor  
                key = get_key(adc_key_in);	// convert into key press
                if (key != oldkey)	
                {
                      switch(key) {
	                 case 4: //SELECT
                            fl_feed = 0;
                            return;
                      }
                }
        }
  }
}


void NeonManual(){

  lcd.cursorTo(0,0);
  if (neon_fl){
    lcd.cursorTo(1, 0);  //line=2, x=0
    lcd.printIn("NEON ON   ");
  }
  else {
    lcd.cursorTo(1, 0);  //line=2, x=0
    lcd.printIn("NEON OFF   ");
  }
  Alarm.delay(500);
  for(;;)
  {
    Alarm.delay(50);
    adc_key_in = analogRead(0);    // read the value from the sensor
    key = get_key(adc_key_in);		        // convert into key press
	if (key != oldkey)				    // if keypress is detected
	{
                Alarm.delay(50);		        // wait for debounce time
		adc_key_in = analogRead(0);     // read the value from the sensor  
                key = get_key(adc_key_in);	// convert into key press
                if (key != oldkey)	
                {
                      switch(key) {
	                 case 1: //UP
	                    lcd.cursorTo(1, 0);  //line=2, x=0
                            lcd.printIn("NEON ON ");
                            NeonOn();
	                    break;
	                 case 2: //DOWN
                            lcd.cursorTo(1, 0);  //line=2, x=0
	                    lcd.printIn("NEON OFF");
                            NeonOff();
	                    break;
	                 case 4: //SELECT
                            return;
                      }
                }
        }
  }
}

void SetStatus(){

  double distance;
  Serial.println("Set Status");
  
  //gets distance
  distance = getLevel();
  if (distance > min_distance)
  {
    //solo dopo la seconda volta
    if (first_distance_fl)
    {
      refill_fl = 1; //corretto
    }
    first_distance_fl = 1;
  }
  else
  {
    first_distance_fl = 0;
    refill_fl = 0;
  }
  
  //gets temperature  
  if(getTemperature()){
  
    if (OneWireTemp > hi_temp){
       cooler_fl = 1;
       Serial.println("temp hi");
    }
    if (OneWireTemp < lo_temp){
       cooler_fl = 0;
       Serial.println("temp lo");
    }
    //EEPROM.write(cooler_pin * 2, cooler_fl);
  }
  
  if (!neon_fl){
     digitalWrite(neon_pin, HIGH);
  }
  else {
     digitalWrite(neon_pin, LOW);
   }

  if (!hqi_fl){
     digitalWrite(hqi_pin, HIGH);
     //TEMPORANEO 
     //digitalWrite(cooler_pin, HIGH);
  }
  else {
     digitalWrite(hqi_pin, LOW);
     //TEMPORANEO 
     //digitalWrite(cooler_pin, LOW);
  }
  
  if (!moon_fl) {
     digitalWrite(moon_pin, HIGH);
  }
  else {
     digitalWrite(moon_pin, LOW);
  }    

  if (!pumpsx_fl or fl_feed) {
     digitalWrite(pumpsx_pin, HIGH);
  }
  else {
     digitalWrite(pumpsx_pin, LOW);
  }    

  if (!pumpdx_fl or fl_feed) {
     digitalWrite(pumpdx_pin, HIGH);
  }
  else {
     digitalWrite(pumpdx_pin, LOW);
  }    

  if (refill_fl or force_refill_fl) {
     digitalWrite(refill_pin, LOW);
  }
  else {
     digitalWrite(refill_pin, HIGH);
  }    

  if (!cooler_fl) {
    digitalWrite(cooler_pin, HIGH);
     Serial.println("spengo cooler");
  }
  else {
    digitalWrite(cooler_pin, LOW);
     Serial.println("accendo cooler");
  }    
}

void HQIOn(){
  //digitalWrite(hqi_pin, HIGH);
  hqi_fl = 1;
  EEPROM.write(hqi_pin * 2, 1);
}

void HQIOff(){
  //digitalWrite(hqi_pin, LOW);
  hqi_fl = 0;
  EEPROM.write(hqi_pin * 2, 0);
}

void HQIManual(){

  lcd.cursorTo(0,0);
  if (hqi_fl){
    lcd.cursorTo(1, 0);  //line=2, x=0
    lcd.printIn("HQI ON       ");
  }
  else {
    lcd.cursorTo(1, 0);  //line=2, x=0
    lcd.printIn("HQI OFF     ");
  }
  Alarm.delay(500);
  for(;;)
  {
    Alarm.delay(50);
    adc_key_in = analogRead(0);    // read the value from the sensor
    key = get_key(adc_key_in);		        // convert into key press
	if (key != oldkey)				    // if keypress is detected
	{
                Alarm.delay(50);		        // wait for debounce time
		adc_key_in = analogRead(0);     // read the value from the sensor  
                key = get_key(adc_key_in);	// convert into key press
                if (key != oldkey)	
                {
                      switch(key) {
	                 case 1: //UP
	                    lcd.cursorTo(1, 0);  //line=2, x=0
                            lcd.printIn("HQI ON    ");
                            HQIOn();
	                    break;
	                 case 2: //DOWN
                            lcd.cursorTo(1, 0);  //line=2, x=0
	                    lcd.printIn("HQI OFF   ");
                            HQIOff();
	                    break;
	                 case 4: //SELECT
                            return;
                      }
                }
        }
  }
}


void MoonOn(){
  //digitalWrite(moon_pin, HIGH);
  moon_fl = 1;
  EEPROM.write(moon_pin * 2, 1);
}

void MoonOff(){
  //digitalWrite(moon_pin, LOW);
  moon_fl = 0;
  EEPROM.write(moon_pin * 2, 0);

}

void MoonManual(){

  lcd.cursorTo(0,0);
  if (moon_fl){
    lcd.cursorTo(1, 0);  //line=2, x=0
    lcd.printIn("Moon ON     ");
  }
  else {
    lcd.cursorTo(1, 0);  //line=2, x=0
    lcd.printIn("Moon OFF    ");
  }
  Alarm.delay(500);
  for(;;)
  {
    Alarm.delay(50);
    adc_key_in = analogRead(0);    // read the value from the sensor
    key = get_key(adc_key_in);		        // convert into key press
	if (key != oldkey)				    // if keypress is detected
	{
                Alarm.delay(50);		        // wait for debounce time
		adc_key_in = analogRead(0);     // read the value from the sensor  
                key = get_key(adc_key_in);	// convert into key press
                if (key != oldkey)	
                {
                      switch(key) {
	                 case 1: //UP
	                    lcd.cursorTo(1, 0);  //line=2, x=0
                            lcd.printIn("Moon ON   ");
                            MoonOn();
	                    break;
	                 case 2: //DOWN
                            lcd.cursorTo(1, 0);  //line=2, x=0
	                    lcd.printIn("Moon OFF   ");
                            MoonOff();
	                    break;
	                 case 4: //SELECT
                            return;
                      }
                }
        }
  }
}

void PumpSwitchSx(){
  PumpSxOn();
  PumpDxOff();
}

void PumpSwitchDx(){
  PumpDxOn();
  PumpSxOff();
}

void PumpSxOn(){
  pumpsx_fl = 1;
  EEPROM.write(pumpsx_pin * 2, 1);
}

void PumpSxOff(){
  pumpsx_fl = 0;
  EEPROM.write(pumpsx_pin * 2, 0);
}

void PumpSxManual(){

  lcd.cursorTo(0,0);
  if (pumpsx_fl){
    lcd.cursorTo(1, 0);  //line=2, x=0
    lcd.printIn("PUMP SX ON  ");
  }
  else {
    lcd.cursorTo(1, 0);  //line=2, x=0
    lcd.printIn("PUMP SX OFF  ");
  }
  Alarm.delay(500);
  for(;;)
  {
    Alarm.delay(50);
    adc_key_in = analogRead(0);    // read the value from the sensor
    key = get_key(adc_key_in);		        // convert into key press
	if (key != oldkey)				    // if keypress is detected
	{
                Alarm.delay(50);		        // wait for debounce time
		adc_key_in = analogRead(0);     // read the value from the sensor  
                key = get_key(adc_key_in);	// convert into key press
                if (key != oldkey)	
                {
                      switch(key) {
	                 case 1: //UP
	                    lcd.cursorTo(1, 0);  //line=2, x=0
                            lcd.printIn("PUMP SX ON ");
                            PumpSxOn();
	                    break;
	                 case 2: //DOWN
                            lcd.cursorTo(1, 0);  //line=2, x=0
	                    lcd.printIn("PUMP SX OFF");
                            PumpSxOff();
	                    break;
	                 case 4: //SELECT
                            return;
                      }
                }
        }
  }
}

void PumpDxOn(){
  pumpdx_fl = 1;
  EEPROM.write(pumpdx_pin * 2, 1);
}

void PumpDxOff(){
  pumpdx_fl = 0;
  EEPROM.write(pumpdx_pin * 2, 0);
}

void PumpDxManual(){

  lcd.cursorTo(0,0);
  if (pumpdx_fl){
    lcd.cursorTo(1, 0);  //line=2, x=0
    lcd.printIn("PUMP DX ON ");
  }
  else {
    lcd.cursorTo(1, 0);  //line=2, x=0
    lcd.printIn("PUMP DX OFF");
  }
  Alarm.delay(500);
  for(;;)
  {
    Alarm.delay(50);
    adc_key_in = analogRead(0);    // read the value from the sensor
    key = get_key(adc_key_in);		        // convert into key press
	if (key != oldkey)				    // if keypress is detected
	{
                Alarm.delay(50);		        // wait for debounce time
		adc_key_in = analogRead(0);     // read the value from the sensor  
                key = get_key(adc_key_in);	// convert into key press
                if (key != oldkey)	
                {
                      switch(key) {
	                 case 1: //UP
	                    lcd.cursorTo(1, 0);  //line=2, x=0
                            lcd.printIn("PUMP DX ON ");
                            PumpDxOn();
	                    break;
	                 case 2: //DOWN
                            lcd.cursorTo(1, 0);  //line=2, x=0
	                    lcd.printIn("PUMP DX OFF");
                            PumpDxOff();
	                    break;
	                 case 4: //SELECT
                            return;
                      }
                }
        }
  }
}

void RefillOn(){
  refill_fl = 1;
  EEPROM.write(refill_pin * 2, 1);
}

void RefillOff(){
  refill_fl = 0;
  EEPROM.write(refill_pin * 2, 0);
}

void RefillManual(){

  lcd.cursorTo(0,0);
  if (refill_fl){
    lcd.cursorTo(1, 0);  //line=2, x=0
    lcd.printIn("RABBOCCO ON ");
  }
  else {
    lcd.cursorTo(1, 0);  //line=2, x=0
    lcd.printIn("RABBOCCO OFF ");
  }
  Alarm.delay(500);
  for(;;)
  {
    Alarm.delay(50);
    adc_key_in = analogRead(0);    // read the value from the sensor
    key = get_key(adc_key_in);		        // convert into key press
	if (key != oldkey)				    // if keypress is detected
	{
                Alarm.delay(50);		        // wait for debounce time
		adc_key_in = analogRead(0);     // read the value from the sensor  
                key = get_key(adc_key_in);	// convert into key press
                if (key != oldkey)	
                {
                      switch(key) {
	                 case 1: //UP
	                    lcd.cursorTo(1, 0);  //line=2, x=0
                            lcd.printIn("RABBOCCO ON ");
                            force_refill_fl = 1;
	                    break;
	                 case 2: //DOWN
                            lcd.cursorTo(1, 0);  //line=2, x=0
	                    lcd.printIn("RABBOCCO OFF");
                            force_refill_fl = 0;
	                    break;
	                 case 4: //SELECT
                            return;
                      }
                }
        }
  }
}

void digitalClockDisplay()
{
  // digital clock display of the time
  Serial.print(hour());
  printDigits(minute());
  printDigits(second());
  Serial.println();
/*  lcd.cursorTo(1, 0);  //line=2, x=0
  lcd.printIn(hour());
  lcd.cursorTo(1, 2);  //line=2, x=0
  lcd.printIn(minute());
  lcd.cursorTo(1, 4);  //line=2, x=0
  lcd.printIn(second()); */
}

void printDigits(int digits)
{
  Serial.print(":");
  if(digits < 10)
    Serial.print('0');
  Serial.print(digits);
} 

void TempManual(){
  float temp;
  int i;int whole; int fract;
  char buffer[16];
  
  lcd.cursorTo(0,0);
  lcd.printIn("TEMPERATURA      ");
  for(;;)
  {
    Alarm.delay(500);
    adc_key_in = analogRead(0);    // read the value from the sensor
    key = get_key(adc_key_in);		        // convert into key press
	if (key != oldkey)				    // if keypress is detected
	{
                Alarm.delay(50);		        // wait for debounce time
		adc_key_in = analogRead(0);     // read the value from the sensor  
                key = get_key(adc_key_in);	// convert into key press
                if (key != oldkey)	
                {
                      switch(key) {
	                 case 4: //SELECT
                            lcd.cursorTo(1, 0);  //line=2, x=0
                            lcd.printIn(msgs[2]);
                            lcd.cursorTo(2, 0);  //line=2, x=0
                            lcd.printIn("                ");
                            return;
                      }
                }
        }
        Serial.print("prima");
        if (getTemperature()){
          //Serial.print(temp/10); Serial.println(" degrees C");
          whole = OneWireTemp/10;
          fract = OneWireTemp*10;
          fract = fract%100;
          sprintf(buffer, "%3d%c%2d", whole, '.', fract);
          lcd.cursorTo(2, 0);  //line=2, x=0
          lcd.printIn(buffer);
        }
  }
}


double Distance(int RawADC) {
  
  double volts = RawADC * 0.0048828125;            // value from sensor * (5/1024) - if running 3.3.volts then change 5 to 3.3
  double distance = 65 * pow(volts, -1.10);  // worked out from graph 65 = theretical distance / (1/Volts)S - luckylarry.co.uk
  return distance;
}


double getLevel(){
        double temp;
        
        for(int i = 0; i < 10; i++)
        { // gets 10 samples of distance
            
            Alarm.delay(50);
            temp += Distance(analogRead(distance_pin)); 
        }
        return temp/10;
}


void Orologio()
{
  char c_anno[12];
  char c_mese[6];
  char c_giorno[6];
  char c_ora[6];
  char c_minuti[6];
  char c_secondi[6];
  char c_tutto[10];
  
  DateTime now;
 
  lcd.clear();
 
  for(;;)
  {
    now = RTC.now();
    Alarm.delay(250);
    
    //Displays this:
    // HH:MM:SS
    // DD.MM.YYYY
    /*
    lcd.cursorTo(1,6);
    itoa(now.hour(),c_ora,10);
    lcd.printIn(c_ora);
    lcd.printIn(":");
    itoa(now.minute(),c_minuti,10);
    lcd.printIn(c_minuti);
    lcd.printIn(":");
    itoa(now.second(),c_secondi,10);
    lcd.printIn(c_secondi);
    lcd.cursorTo(2,6);
    itoa(now.day(),c_giorno,10);
    lcd.printIn(c_giorno);
    lcd.printIn(".");
    itoa(now.month(),c_mese,10);
    lcd.printIn(c_mese);
    lcd.printIn(".");
    itoa(now.year(),c_anno,10);
    lcd.printIn(c_anno);
    */
    int n = sprintf(c_tutto, "%02d%c%02d%c%02d", now.hour(),':',now.minute(), ':', now.second());
    c_tutto[8] = 0;
    lcd.cursorTo(1,6);
    lcd.printIn(c_tutto);
    n = sprintf(c_tutto, "%02d%c%02d%c%04d", now.day(),':',now.month(), ':', now.year());
    c_tutto[10] = 0;
    lcd.cursorTo(2,6);
    lcd.printIn(c_tutto);
       
    
    adc_key_in = analogRead(0);    // read the value from the sensor
    key = get_key(adc_key_in);		        // convert into key press
	if (key != oldkey)				    // if keypress is detected
	{
                Alarm.delay(50);		        // wait for debounce time
		adc_key_in = analogRead(0);     // read the value from the sensor  
                key = get_key(adc_key_in);	// convert into key press
                if (key != oldkey)	
                {
                      switch(key) {
	                 case 4: //SELECT
                            lcd.cursorTo(1, 0);  //line=2, x=0
                            lcd.printIn(msgs[9]);
                            lcd.cursorTo(2, 0);  //line=2, x=0
                            lcd.printIn("                ");
                            return;
                      }
                }
        }
  }
} 

void CoolerOn(){
  //digitalWrite(hqi_pin, HIGH);
  cooler_fl = 1;
  EEPROM.write(cooler_pin * 2, 1);

}

void CoolerOff(){
  //digitalWrite(hqi_pin, LOW);
  cooler_fl = 0;
  EEPROM.write(cooler_pin * 2, 0);

}

void CoolerManual(){

  lcd.cursorTo(0,0);
  if (cooler_fl){
    lcd.cursorTo(1, 0);  //line=2, x=0
    lcd.printIn("COOLER ON    ");
  }
  else {
    lcd.cursorTo(1, 0);  //line=2, x=0
    lcd.printIn("COOLER OFF  ");
  }
  Alarm.delay(500);
  for(;;)
  {
    Alarm.delay(50);
    adc_key_in = analogRead(0);    // read the value from the sensor
    key = get_key(adc_key_in);		        // convert into key press
	if (key != oldkey)				    // if keypress is detected
	{
                Alarm.delay(50);		        // wait for debounce time
		adc_key_in = analogRead(0);     // read the value from the sensor  
                key = get_key(adc_key_in);	// convert into key press
                if (key != oldkey)	
                {
                      switch(key) {
	                 case 1: //UP
	                    lcd.cursorTo(1, 0);  //line=2, x=0
                            lcd.printIn("COOLER ON   ");
                            CoolerOn();
	                    break;
	                 case 2: //DOWN
                            lcd.cursorTo(1, 0);  //line=2, x=0
	                    lcd.printIn("COOLER OFF  ");
                            CoolerOff();
	                    break;
	                 case 4: //SELECT
                            return;
                      }
                }
        }
  }
}


void TestDistanza(){
  double distance;
  int i;int whole; int fract;
  char buffer[16];
 
  lcd.cursorTo(0,0);
  lcd.printIn("DISTANZA MIS.");
  Serial.println("DISTANZA MISURATA");;
  for(;;)
  {
    Alarm.delay(500);
    adc_key_in = analogRead(0);    // read the value from the sensor
    key = get_key(adc_key_in);		        // convert into key press
	if (key != oldkey)				    // if keypress is detected
	{
                Alarm.delay(50);		        // wait for debounce time
		adc_key_in = analogRead(0);     // read the value from the sensor  
                key = get_key(adc_key_in);	// convert into key press
                if (key != oldkey)	
                {
                      switch(key) {
	                 case 4: //SELECT
                            lcd.cursorTo(1, 0);  //line=2, x=0
                            lcd.printIn(msgs[2]);
                            lcd.cursorTo(2, 0);  //line=2, x=0
                            lcd.printIn("                ");
                            return;
                      }
                }
        }
        distance = getLevel();
        char buffer[16];
        whole = distance/10*10;
        fract = distance*10;
        fract = fract%100;
        sprintf(buffer, "%3d%c%02d", whole, '.', fract);
        lcd.cursorTo(2, 0);  //line=2, x=0
        lcd.printIn(buffer);
        Serial.println(buffer);
  }
}


  boolean getTemperature(){
  byte i;
  byte present = 0;
  byte data[12];
  
  //find a device
  ds.reset_search();
  if (!ds.search(addr)) {
    ds.reset_search();
    //Serial.print("minchiacazzo");
    return false;
  }
  if (OneWire::crc8( addr, 7) != addr[7]) {
    //Serial.print("cazzominchia");
    return false;
  }
  if (addr[0] != DS18S20_ID && addr[0] != DS18B20_ID) {
    //Serial.print("quaddentro");
    return false;
  }
  ds.reset();
  ds.select(addr);
  // Start conversion
  ds.write(0x44, 1);
  // Wait some time...
  Alarm.delay(850);
  present = ds.reset();
  ds.select(addr);
  // Issue Read scratchpad command
  ds.write(0xBE);
  // Receive 9 bytes
  for ( i = 0; i < 9; i++) {
    data[i] = ds.read();
  }
  
  // Calculate temperature value
  OneWireTemp = ( (data[1] << 8) + data[0] )*0.0625;
  Serial.print(OneWireTemp);
  return true;
 
}
